/*persevere-partial 
/**
Illuminate - Browser side widget/templating engine with reversibility capabilites and event handling, and url history
Copyright (C) 2007 Xucia Incorporation
Author - Kris Zyp - kriszyp@xucia.com
 */   
temp={_id:'illuminate.js'};
(function() {
	var isIE = !(!document.all);
	debugMode =document.location.search.indexOf("debug=true") > -1;
	Page=persevere.init({id:'js/Page',
		name:{type:'string'},
		title:{type:'string'},
		body:{type:'*'},
		keywords:{type:'string'},
		description:{type:'string'}
		});
	Context=persevere.init({id:'js/Context',ready:1});
	
    /**
     * AOP style event handling
     **/
	var _eventElements = [];
    var _eventListeners = [];
    var currentEventOperator;    
	events = {
		/* Add a listener for the execution of the given function slot on the given object.
		 * When object[functionName]() is executed the handler is called.
		 * The optional listeningType parameter specificies (using the constants below) whether handler
		 * should be fired before, after or around the previously registered handler or default action
		 * If a the event is a DOM event, than you can provide the name of the event instead of the
		 * handler name, that is you can register for the click events with "click" (event name) or "onclick" (handler name).
		 * 
		 */
		addListener : function(object,functionName,handler,listeningType) {
			if (!handler)
				throw new Error("No handler provided");
			var isDOM = object.nodeType;
			if (isDOM && functionName.substring(0,2) != "on") functionName = "on" + functionName;
			var handlers;
			var oldHandler = object[functionName];
			if (oldHandler && oldHandler.$_handlers)
				handlers = oldHandler.$_handlers;
			else
			{
				if (isDOM && isIE) { // this is for cleanup
					_eventElements.push(object);
					_eventListeners.push(functionName);
				}
				object[functionName] = function(evt) {
					if (isDOM && !evt) { // this is for IE
						arguments[0] = evt = window.event || parent.event;
						evt.target = evt.srcElement;
						arguments.length = 1;
						evt.preventDefault = events.iePreventDefault;
						evt.stopPropagation = events.ieStopPropagation;
					}
					if (!isIE)
						event = evt; // make it globally availabe for IE style access
					currentEventOperator=function(action) {
						if (action==0)
							handlers.splice(i,1);
						if (action==1)
							return [oldHandler,object];
					}
					for (var i =  handlers.length; i>0;)
					{
						i--;
						try {
							pjs; // fix the problem when the event is in the wrong window
						}
						catch(e) {return}
						var retValue = pjs.transaction(handlers[i],object,arguments);
					}						
					return retValue; 
				}
				//object[functionName].clientOnly=1; 
				handlers = object[functionName].$_handlers = oldHandler?[oldHandler]:[];
			}
			if (Array.indexOf(handlers,handler) == -1) {
				if (listeningType == 1)
					handlers.push(handler);
				if (!listeningType) // or == 0
					handlers.splice(0,0,handler); // insert it at the beginning
			}
			return handler;
		},
		/** Remove a previously a previously registered handler from listening */
		removeListener : function(object,functionName,handler) {
			var isDOM = object.nodeType;
			if (isDOM && functionName.substring(0,2) != "on") functionName = "on" + functionName;
			var handlers = object[functionName].$_handlers;
			var index = Array.indexOf(handlers,handler);
			if (index >= 0)
				handlers.splice(index,1);				
		},
        // The different styles of listening
		AFTER:0,  // indicates listener fires after the previously registered or default action
		BEFORE:1,// indicates listener fires before the previously registered or default action
		AROUND:2,// indicates listener fires and must call doNext for the previously registered or default action
		/* This can be called when in a handler to remove the handler as a listener for the current event */
		stopListening : function() {
			currentEventOperator(0);
		},
		/* In around handling, call this for the previous registered event */
		doNext : function() {
			var callSet = currentEventOperator(1);
			return callSet[0].apply(callSet[1],arguments);
		},
		/* Simulate the W3C action for IE*/
        iePreventDefault: function() { 
            this.returnValue = false;
        },
        /* Simulate the W3C action for IE*/
        ieStopPropagation: function() { 
            this.cancelBubble = true;
        },
		/** remove all the listeners for IE, so there is no memory leaks */
		cleanupListeners : function() { 
			if (isIE) {
				for (var i = 0; i < _eventElements.length; i++) {
					_eventElements[i][_eventListeners[i]] = null;
				}
				_eventElements=null;
			}
		}
	}
	if (isIE)
		events.addListener(window,"onunload",ourcustomunloader=function () {
			illum.rootContext.clearChildren();
			events.cleanupListeners();
			//purge(parent.document.body);
		});
	var userData = _S;
	var getUserData = pjs.getUserData;
	var get = pjs.get;
	if (!window.util)
		util = {};
		/*
		 * Converts a string that like 34px to a number like 34.
		 */
		util.convertDimToNum = function (str) {
			if (str=="" || str=="auto")
				return 0;
			if (str.indexOf("px") > -1)
				str =str.substring(0,str.indexOf("px"));
			return 1*str;
		}	
		util.contextDataRoots = {};
		util.cleanup=function () {
			// TODO: Any cleanup operations, maybe IE garbage collection
		}
		
	var contextsToRender;
	var FRAME_LENGTH = 40; // time in milliseconds for a frame of animation
	var waitingForFrame,lastFrame; 
	// this is used to coordinate synchronized frames
	var setupAnimationFrames = function(){
		if (!waitingForFrame) { // we need to create the queue
					waitingForFrame = []; // start a queue
					var executeNextFrame = function() {
						if (waitingForFrame.length == 0) {// nothing got added before the frame, go back to rest state
							waitingForFrame=0;
							lastFrame = 0;
						}
						else {
							var thisFrameTime = new Date().getTime();
							lastFrame += FRAME_LENGTH;
							var delay = lastFrame - thisFrameTime + FRAME_LENGTH;
							var doFrame = delay > 1;
							delay = doFrame ? delay : 1;
							setTimeout(executeNextFrame,delay);
							var waiting = waitingForFrame;
							waitingForFrame=[];
							for (var i=0; i < waiting.length;i++)
								waiting[i](doFrame); 
						}
					}
					lastFrame = new Date().getTime();
					setTimeout(executeNextFrame,FRAME_LENGTH);
				}	
	}
	// This is part of the UI framework
	_p(


/*	pjs.accessDenied = function(obj) {						*/pjs,"accessDenied",function(obj){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:
/*		var username; 						*/var username;_cp=2;case 2:if((_f.v2=_g(
/*		if (username = pjs.getUserName(pjs.hostForId(obj._id))) {						*/obj,"_id"))===_S){break _s;}_cp=3;case 3:if((_f.v3=pjs.hostForId(_f.v2))===_S){break _s;}_cp=4;case 4:if((_f.v4=pjs.getUserName(_f.v3))===_S){break _s;}_cp=(username=_f.v4)?5:6;break;case 5:_cp=8;case 8:if((_f.v8=
/*			if (confirm("You do not have access to this content.  Would you like to request access?"))						*/confirm("You do not have access to this content.  Would you like to request access?"))===_S){break _s;}_cp=(_f.v8)?9:10;break;case 9:_cp=11;case 11:if((_f.v11=
/*				util.serverAction("com.xucia.auth.action.Request","requestAccess",{username:username});						*/util.serverAction("com.xucia.auth.action.Request","requestAccess",{username:username}))===_S){break _s;}_cp=10;break;case 10:_cp=7;break;case 6:_cp=12;case 12:if((_f.v12=
/*		}						*/
/*		else {						*/
/*			if (confirm("You do not have access to this content.  Would you like to login?")) {						*/confirm("You do not have access to this content.  Would you like to login?"))===_S){break _s;}_cp=(_f.v12)?13:14;break;case 13:_cp=15;case 15:if((_f.v15=_g(
/*				illum.login(pjs.hostForId(obj._id));						*/obj,"_id"))===_S){break _s;}_cp=16;case 16:if((_f.v16=pjs.hostForId(_f.v15))===_S){break _s;}_cp=17;case 17:if((_f.v17=illum.login(_f.v16))===_S){break _s;}_cp=18;case 18:if((_f.v18=_f._new(
/*				return new Future().result();// TODO: make it resume when login is finished.						*/Future))===_S){break _s;}_cp=19;case 19:if((_f.v19=_f.v18.result())===_S){break _s;}return _f.v19;_cp=14;break;case 14:_cp=7;break;case 7:_cp=20;case 20:if((_f.v20=_f._new(
/*			}						*/
/*		}						*/
/*		throw new Error("You do not have access to this content"); 						*/Error,["You do not have access to this content"]))===_S){break _s;}throw(_f.v20);return;case 0:username=_f[0];obj=_f[1];_cp=_f.cp;}}return _f.sus(username,obj,_cp,this)});
/*								*/

	var contextMap = {};
	illum = {
		isIE : isIE,
		editmode : false,
		
		/** 
		 * This adds the given context as a listener to the given event
		 */
		addContextListener : function(context,object,handlerName) {
			if (!handlerName) {
				handlerName = pjs.getId(object);
				object = pjs.changeNotificationList;
			}
			events.addListener(object,handlerName,contextMap[context.id] || 
				(contextMap[context.id] = function() {
					if (context.isOrphaned())
						events.stopListening();
					else {
						if (contextsToRender) {
							if (Array.indexOf(contextsToRender,context) == -1)
								contextsToRender.push(context);
						}
						else { 
							contextsToRender =[context];
							setTimeout(function() {
								for (var i = 0; i < contextsToRender.length; i++)
									if (!contextsToRender[i].isOrphaned())
										contextsToRender[i].render();
								contextsToRender=0;
							},10);
						}
					}
				}));
		},
		navigate : function(location) { // navigate to the given name
			illum.rootContext.navigate(location);
		},
		dragInit : function() {
			//TODO: implement this
			//throw new Error("Not implemented yet");
		},
		/** 
		 * Turn on editing for the current page
		 */
		editThisPage : function(hash) { 
			location.href = location.href.substring(0,location.href.indexOf("#")) + "edit#" + (hash || urlHistory.getHash());
		},
		evaluateField : function(context,value) { //TODO: move this to a lower scope level for better performance
			var field = context.element.getAttribute("field");
			if (!field || field.length == 0)
				return context.content;
			var fields = field.split('.');
			for (var i = 0; i < fields.length; i++) {
				var doSet;// = (vaue && (i + 1 == fields.length));
					if (i==0)
						with(context) {if ((context = eval(fields[0] + (doSet?"=value":""))) === _S) return _S; }
					else
						if ((context = (doSet?set:illum.trackedGet)(context,fields[i],value || !doSet)) === _S) return _S;
			}
			return context;
		},
		/**
		 * Returns the context for the given DOM element
		 */
		getContext :	function(element) {
			do {
				if (element.context)
					return element.context;
				element = element.parentNode;
			} while (element);
		},
		/**
		 * Returns the next animation frame. This will sleep up to 40 milliseconds and the resume execution at the same time as the next animation frame 
		 * so that animation can take place in one chunk of javascript and run smoother
		 */
		waitForNextFrame : function() {
			var njf = _frm(arguments);
			if (!njf.notifier) { // if it is zero
				setupAnimationFrames();
				waitingForFrame.push((njf.notifier = new Future).fulfill);
				njf.notifier.result();
				return njf.sus(this);
			}
			return njf.notifier.result(); // this is the wait operation to resume
		},
		/**
		 * This will call the given updater for the given amount of time and each call will provide a percentage of completion of the animation.
		 * The animation updater can do any DOM updates based upon the percentage for each call. The animation uses an easing function to provide 
		 * smooth animation.
		 * @param length The length of time of the animation in milliseconds.
		 * @param updater The function to call for each step in the animation
		 */
		animate : function(length,updater) {
			var iterations = length / FRAME_LENGTH;
			var func = function(doFrame) {
				var i = func.i++;
				if (i < iterations) {
					if (doFrame) // skip the frame if necessary
						updater((1-Math.cos(i / iterations * Math.PI))/2); // sinusoidal easing function
					waitingForFrame.push(func); // make sure it gets added to the next frame
				}
				else if (i!=0) // -1/0 indicates it was cancelled
					updater(1);
			}
			setupAnimationFrames();
			waitingForFrame.push(func);
			func.i=1;
			return {cancel: function() {
				func.i=-1;}
			}
		},
		/**
		 * This will create a popup in the given context.
		 * @param context The context to create the popup in
		 * @param element optional element to use as the popup
		 * @return the new context for the popup
		 */
		popupContext : function(context, element) {
				if (!element)  {
					element = parent.document.createElement("div");
					element.style.width="450px";					
				}
				(byId("popupContainer") || document.body).appendChild(element); // TODO: this should create from something different
				if (!context)
					context = illum.rootContext;
				return context.createChild(element);			
		},
		/**
		 * Creates a dialog
		 */
		createDialog : function(context,header,body,footer,element) {
			var njf = _frm(arguments);
			if (!njf.cp) {
				context = illum.popupContext(context,element);
				context.body = body;
				context.header=header;
				context.footer = footer;
				njf.context = context;
			}
			njf.cp=1;
			context = njf.context;
			var popup = pjs.load("js/popup.js?1");
			if (popup==_S ||
				popup.render(context)==_S) return njf.sus(this);
			return context;
		},
	     getElementsBy: function(method, tag, root) {
	         tag = tag || '*';
	         root = root || document;
	
	         var nodes = [];
	         var elements = root.getElementsByTagName(tag);
	
	         if ( !elements.length && (tag == '*' && root.all) ) {
	            elements = root.all; // IE < 6
	         }
	
	         for (var i = 0, len = elements.length; i < len; ++i)
	         {
	            if ( method(elements[i]) ) { nodes[nodes.length] = elements[i]; }
	         }
		
	         return nodes;
	    },
	    /**
	     * For IE 6 and lower this fixes all the pngs.
	     */
		fixPng : function (source) {
		      	source.onload = function() {
			         var imgId = (source.id) ? "id='" + source.id + "' " : ""
			         var imgClass = (source.className) ? "class='" + source.className + "' " : ""
			         var imgTitle = (source.title) ? "title='" + source.title + "' " : "title='" + source.alt + "' "
			         var imgStyle = "display:inline-block;" + source.style.cssText
			         if (source.align == "left") imgStyle = "float:left;" + imgStyle
			         if (source.align == "right") imgStyle = "float:right;" + imgStyle
			         if (source.parentElement.href) imgStyle = "cursor:hand;" + imgStyle;
			         var strNewHTML = "<span contentEditable=\"false\" " + imgId + imgClass + imgTitle
			         + " style=\"" + "width:" + source.width + "px; height:" + source.height + "px;" + imgStyle + ";"
			         + "filter:progid:DXImageTransform.Microsoft.AlphaImageLoader"
			         + "(src=\'" + source.src + "\', sizingMethod='scale');\" pngFix=true></span>";
			         source.outerHTML = strNewHTML;
			         source.onload = null;
		     	}
	      	},
	     /**
	      * Apply the given CSS to the element, encapsulated the CSS to this element (by prepending the element id to each selector)
	      * @param element The element (and sub elements) to apply the CSS to
	      * @param styles The css to apply
	      */
      	applyStyles : function(element,styles) {
			var doc = element.ownerDocument;
      		var id = element.id;
      		if(!id) {
			  id = "tempid"+ pjs.getId((styles.parent || styles)).replace(/[^\w]/g,"");
			  while (doc.getElementById(id))
			  	id += "1";
			  element.id = id;
      		}
			var global = element.id == "renderingBody" && illum.fullPage && !(illum.editmode && isIE);
			var prefix = global?"":"#" + id + " ";
		 	if (styles instanceof String || typeof styles == "string") // TODO: Need to add the body when we are global and it is blank in the CSS
		 		var cssStr = global ? styles : styles.replace(/\s*(body)?([^\}\{]*)\{/gi,"\n" + prefix + "$2{");

		 	else if (styles){				 	
			    var cssStr = "";
			    if (Array.forEach(styles,function(styleObj) {
			    	var name = get(styleObj,"name");
			    	var cssText = get(styleObj,"cssText");
			    	if (name === _S || cssText === _S)
			    		return _S;
			    	cssStr += prefix + name + " {\n" + cssText + "\n}\n";       
			    }) === _S) return strands.rerunLater(this,arguments);
		 	}
		 	if (!cssStr)
		 		return;
		    id = id + "__style__";
			var head = doc.getElementsByTagName("head")[0];
			var style = doc.getElementById(id);
			 if (!style) {// if this particular id of style already exists, remove it
				style = doc.createElement("style");
				style.setAttribute("type", "text/css");
				head.appendChild(style);
				style.id = id;
			}
			 if(style.styleSheet){// IE
			  style.styleSheet.cssText = cssStr;
			 } else {// w3c
					var cssText = doc.createTextNode(cssStr);
					if (style.childNodes[0]) 
						style.replaceChild(cssText,style.childNodes[0])
					else 
						style.appendChild(cssText);
			 }
			return style;
      	},
      	showWidget : function(component, context) { // TODO: Move this to the database
      			if (context && context.getElementsByTagName) // it is an element
      				context = illum.rootContext.createChild(context); // convert it to a context
      			
				// TODO: terminate any other threads that are currently rendering this component.
				//debug("rendering " + context.element.getAttribute("field"));
				var njf1 = _frm(arguments);
				
				if (!context) { // this means we are resuming
					if (njf1.context.isOrphaned()) {
						debug("abandoning the rendering of an orphaned context");
						strands.clearSuspension();
						return;
					}
				}
				else {
					njf1.context = context;
					njf1.context.component = component;
					if (njf1.context.element == null) {
						//debug("abandoning the rendering of an orphaned context with no element");
						strands.clearSuspension();
						return; 
					}
				}
				if (njf1.context.noRefresh)
					return;
/*				var lastContext = currentThread.currentContext;  // TODO: can the currentThread.currentContext and the currentExecuter be the same thing?
				currentThread.currentContext = njf1.context;
				currentThread.currentContext.triggers = {};*/
//				debug("rendering " + this);
				if (njf1.context.component.render(njf1.context)== _S) {
					njf1.sus(this); // so we will at the bottom of the resume stack and resume this function
				}
				return njf1.context;
				//currentThread.currentContext = lastContext;
			},
			/** 
			 * Returns a tracking object that contains the object, field, and return value. The tracking object can be used to change the value by UI
			 */
			trackedGet : function(obj,field) { // TODO: This doesn't need to be in pjs
				var retValue = pjs.get(obj,field);
				if (typeof retValue == "string" || typeof retValue == "number" || typeof retValue == "boolean") {
					retValue = new Object(retValue);
					retValue.parent = obj;
					retValue.field = field;
					retValue.isField = true;
				}
				if (retValue == _S) return strands.rerunLater(this,arguments);
				return retValue;				
			},
			
			byIdOrCreate : function(id,tag) {
				var element = byId(id);
				if (!element) {
					element = document.body.appendChild(document.createElement(tag));
					element.id=id;
				}
				return element;					
			}
      	
	};
	_p(

/*		illum.login = function(host) { 						*/illum,"login",function(host){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*			if (pjs.getUserName(host)) {						*/pjs.getUserName(host))===_S){break _s;}_cp=(_f.v2)?3:4;break;case 3:_cp=5;case 5:if((_f.v5=
/*				if (confirm("Are you sure you want to sign out?")) {						*/confirm("Are you sure you want to sign out?"))===_S){break _s;}_cp=(_f.v5)?6:7;break;case 6:_cp=8;case 8:if((_f.v8=
/*					createCookie((host || '')+ 'Auth','',-1);						*/createCookie((host||"")+"Auth","",-1))===_S){break _s;}_cp=9;case 9:if((_f.v9=_g(
/*					top.location.reload();						*/top,"location"))===_S){break _s;}_cp=10;case 10:if((_f.v10=_f.v9.reload())===_S){break _s;}_cp=7;break;case 7:
/*				}						*/
/*				return;						*/return;_cp=4;break;case 4:_cp=11;case 11:if((_f.v11=
/*			}						*/
/*			var loginComponent = pjs.load('js/signin.js');						*/pjs.load("js/signin.js"))===_S){break _s;}var loginComponent=_f.v11;_cp=12;case 12:if((_f.v12=_g(
/*			illum.createDialog(illum.rootContext,"Sign in",loginComponent).host = host;						*/illum,"rootContext"))===_S){break _s;}_cp=13;case 13:if((_f.v13=illum.createDialog(_f.v12,"Sign in",loginComponent))===_S){break _s;}_p(_f.v13,"host",host);return;case 0:loginComponent=_f[0];host=_f[1];_cp=_f.cp;}}return _f.sus(loginComponent,host,_cp,this)});_p(
/*			//loginComponent.render(loginContext);						*/
/*		}						*/
/*	illum.loadWebsite=function(){						*/illum,"loadWebsite",function(){var arVersion,content,layout,contextCleanup,root,_cp=1;var _f=_frm(arguments);return _f.clsr(function(){_s:while(1){switch(_cp){case 1:
/*		var content,layout,arVersion,contextCleanup;						*/content,layout,arVersion,contextCleanup;_cp=2;case 2:if((_f.v2=_g(
/*		if (illum.editmode)						*/illum,"editmode"))===_S){break _s;}_cp=(_f.v2)?3:4;break;case 3:_cp=5;case 5:if((_f.v5=
/*			getUserData() // if we are in edit mode this should trigger the first prefetching						*/getUserData())===_S){break _s;}_cp=4;break;case 4:_cp=6;case 6:if((_f.v6=
/*		website=pjs.load("website");						*/pjs.load("website"))===_S){break _s;}website=_f.v6;_cp=7;case 7:if((_f.v7=
/*		var root=pjs.load("root");						*/pjs.load("root"))===_S){break _s;}root=_f.v7;_cp=8;case 8:if((_f.v8=_g(
/*		illum.bodyContext=illum.rootContext.createChild(byId("renderingBody"));						*/illum,"rootContext"))===_S){break _s;}_cp=9;case 9:if((_f.v9=byId("renderingBody"))===_S){break _s;}_cp=10;case 10:if((_f.v10=_f.v8.createChild(_f.v9))===_S){break _s;}_p(illum,"bodyContext",_f.v10);_cp=11;case 11:if((_f.v11=_g(
/*		if (util.onEntryDataLoaded)						*/util,"onEntryDataLoaded"))===_S){break _s;}_cp=(_f.v11)?12:13;break;case 12:_cp=14;case 14:if((_f.v14=
/*			util.onEntryDataLoaded();						*/util.onEntryDataLoaded())===_S){break _s;}_cp=13;break;case 13:_cp=15;case 15:if((_f.v15=_g(
/*		illum.bodyContext.content=website.content;						*/illum,"bodyContext"))===_S){break _s;}_cp=16;case 16:if((_f.v16=_g(website,"content"))===_S){break _s;}_p(_f.v15,"content",_f.v16);_cp=17;case 17:if((_f.v17=_g(
/*		illum.addContextListener(illum.bodyContext,website.content);						*/illum,"bodyContext"))===_S){break _s;}_cp=18;case 18:if((_f.v18=_g(website,"content"))===_S){break _s;}_cp=19;case 19:if((_f.v19=illum.addContextListener(_f.v17,_f.v18))===_S){break _s;}_cp=20;case 20:if((_f.v20=_g(
/*		//illum.rootContext.element=document.body;						*/
/*		illum.bodyContext.component=website.layout;						*/illum,"bodyContext"))===_S){break _s;}_cp=21;case 21:if((_f.v21=_g(website,"layout"))===_S){break _s;}_p(_f.v20,"component",_f.v21);_cp=22;case 22:if((_f.v22=_g(
/*		illum.showWidget(website.layout,illum.bodyContext);						*/website,"layout"))===_S){break _s;}_cp=23;case 23:if((_f.v23=_g(illum,"bodyContext"))===_S){break _s;}_cp=24;case 24:if((_f.v24=illum.showWidget(_f.v22,_f.v23))===_S){break _s;}
/*		contextCleanup=function(){ 						*/contextCleanup=function(){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*		setTimeout(contextCleanup,200);//TODO:  reenable context cleanup						*/setTimeout(contextCleanup,200))===_S){break _s;}return;case 0:_cp=_f.cp;}}return _f.sus(_cp,this)};_cp=25;case 25:if((_f.v25=
/*		}						*/
/*		 						*/
/*		contextCleanup();						*/contextCleanup())===_S){break _s;}_p(
/*		delete illum.loadWebsite;						*/illum,"loadWebsite");_cp=26;case 26:if((_f.v26=_g(
/*		if (illum.targetPageName!="null")						*/illum,"targetPageName"))===_S){break _s;}_cp=(_f.v26!="null")?27:28;break;case 27:_cp=29;case 29:if((_f.v29=_g(
/*			urlHistory.addLocationToHistory(illum.targetPageName);						*/illum,"targetPageName"))===_S){break _s;}_cp=30;case 30:if((_f.v30=urlHistory.addLocationToHistory(_f.v29))===_S){break _s;}_cp=28;break;case 28:_cp=31;case 31:if((_f.v31=
/*		urlHistory.checkURL();						*/urlHistory.checkURL())===_S){break _s;}return;}}return _f.sus(this)}).call(this)});_p(
/*	}  						*/
/*							*/
/*	illum.selectFromList = function(list,title,quickPopup,popupMenu) { // TODO: When a UI object is created in the database, this should go in it.							*/illum,"selectFromList",function(list,title,quickPopup,popupMenu){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=_g(
/*		var menuDiv = parent.document.createElement("div");						*/parent,"document"))===_S){break _s;}_cp=3;case 3:if((_f.v3=_f.v2.createElement("div"))===_S){break _s;}var menuDiv=_f.v3;_cp=4;case 4:if((_f.v4=
/*		(byId("popupContainer") || document.body).appendChild(menuDiv);						*/byId("popupContainer"))===_S){break _s;}_f.c4=_f.v4;_cp=(!_f.c4)?5:6;break;case 5:_cp=7;case 7:if((_f.v7=_g(document,"body"))===_S){break _s;}_f.c4=_f.v7;_cp=6;break;case 6:_cp=8;case 8:if((_f.v8=(_f.c4).appendChild(menuDiv))===_S){break _s;}_cp=9;case 9:if((_f.v9=_g(
/*		var context = illum.rootContext.createChild(menuDiv);						*/illum,"rootContext"))===_S){break _s;}_cp=10;case 10:if((_f.v10=_f.v9.createChild(menuDiv))===_S){break _s;}var context=_f.v10;_p(
/*		context.content = list;						*/context,"content",list);_cp=11;case 11:if((_f.v11=
/*		illum.addContextListener(context,list);						*/illum.addContextListener(context,list))===_S){break _s;}_p(
/*		context.header=title;						*/context,"header",title);_p(
/*		context.footer = "";						*/context,"footer","");_cp=12;case 12:if((_f.v12=_g(
/*		var evt = window.event || parent.event;						*/window,"event"))===_S){break _s;}_f.c12=_f.v12;_cp=(!_f.c12)?13:14;break;case 13:_cp=15;case 15:if((_f.v15=_g(parent,"event"))===_S){break _s;}_f.c12=_f.v15;_cp=14;break;case 14:var evt=_f.c12;
/*		if (evt) {						*/_cp=(evt)?16:17;break;case 16:
/*			var maxHeight = 250;						*/var maxHeight=250;_cp=18;case 18:if((_f.v18=_g(
/*			var winHeight = window.innerHeight || document.documentElement.clientHeight;						*/window,"innerHeight"))===_S){break _s;}_f.c18=_f.v18;_cp=(!_f.c18)?19:20;break;case 19:_cp=21;case 21:if((_f.v21=_g(document,"documentElement"))===_S){break _s;}_cp=22;case 22:if((_f.v22=_g(_f.v21,"clientHeight"))===_S){break _s;}_f.c18=_f.v22;_cp=20;break;case 20:var winHeight=_f.c18;_cp=23;case 23:if((_f.v23=_g(
/*			menuDiv.style.top = ((evt.clientY + maxHeight > winHeight) ? winHeight-maxHeight : evt.clientY) + "px";						*/menuDiv,"style"))===_S){break _s;}_cp=24;case 24:if((_f.v24=_g(evt,"clientY"))===_S){break _s;}_f.c24;_cp=((_f.v24+maxHeight>winHeight))?25:26;break;case 25:_f.c24=winHeight-maxHeight;_cp=27;break;case 26:_cp=28;case 28:if((_f.v28=_g(evt,"clientY"))===_S){break _s;}_f.c24=_f.v28;_cp=27;break;case 27:_p(_f.v23,"top",(_f.c24)+"px");_cp=29;case 29:if((_f.v29=_g(
/*			menuDiv.style.left = evt.clientX + "px";						*/menuDiv,"style"))===_S){break _s;}_cp=30;case 30:if((_f.v30=_g(evt,"clientX"))===_S){break _s;}_p(_f.v29,"left",_f.v30+"px");_cp=17;break;case 17:_cp=31;case 31:if((_f.v31=_g(
/*		}						*/
/*		menuDiv.style.width="150px";						*/menuDiv,"style"))===_S){break _s;}_p(_f.v31,"width","150px");_cp=32;case 32:if((_f.v32=
/*		var selector = pjs.load('js/popup.js');						*/pjs.load("js/popup.js"))===_S){break _s;}var selector=_f.v32;_cp=33;case 33:if((_f.v33=
/*		return selector.selectFromList(context,quickPopup); // Maybe some of this code should move into selectFromList						*/selector.selectFromList(context,quickPopup))===_S){break _s;}return _f.v33;return;case 0:menuDiv=_f[0];maxHeight=_f[1];context=_f[2];evt=_f[3];winHeight=_f[4];selector=_f[5];list=_f[6];title=_f[7];quickPopup=_f[8];popupMenu=_f[9];_cp=_f.cp;}}return _f.sus(menuDiv,maxHeight,context,evt,winHeight,selector,list,title,quickPopup,popupMenu,_cp,this)})
	
	var changeOccuring = false;
	util.contextsNeedingRefreshing = [];
	persevere.changedObject = function(changedObject) {
		contexts = util.contextsNeedingRefreshing;
		while (changedObject) {
			if (context=util.contextDataRoots[changedObject._id]) {// set and test
				if (Array.indexOf(contexts,context) == -1)
					contexts[contexts.length]=context;
				break;
			}
			changedObject = get(changedObject,"parent");
			if (changedObject == _S)
				changedObject = {id:"0"};
		}
		if (!pjs.writeInProgress()&&!changeOccuring) {
			changeOccuring = true;
//			debug("changeOccurred");
			// find affected childMods and derivatives
			setTimeout(function() {
				var contextsNeedingRefreshing = util.contextsNeedingRefreshing;
				changeOccuring = false;
				if (util.postponeRefresh)
					return util.changeOccurred();
				for (var i = 0; i < contextsNeedingRefreshing.length; i++) { // check if this is a child context, because it will get recreated anyway
				
					var parentContext = contextsNeedingRefreshing[i].parent;
					while (parentContext) {
						if (Array.indexOf(contextsNeedingRefreshing,parentContext) != -1) {
							contextsNeedingRefreshing.splice(i--,1);
							break;
						}
						parentContext = parentContext.parent;
					}
				}
				for (var i = 0; i < contextsNeedingRefreshing.length; i++) {
					strands.errorWrapper(function() {
						if (contextsNeedingRefreshing[i].component)
							illum.showWidget(contextsNeedingRefreshing[i].component,contextsNeedingRefreshing[i]);
						else {
							var children = contextsNeedingRefreshing[i].children;
							for (var j = 0; j < children.length; j++)								
								contextsNeedingRefreshing.push(children[j]);
						}
					})();
				}
				util.contextsNeedingRefreshing=[];
			},40);
		}
	}

	var lastMessageCheckDuration=5000;
	var lastMessageCheckTime = 0;
	var userIsDead;
	var lastTimeout;
	var checkForChanges = function() {
		pjs.checkForChanges();
		lastMessageCheckTime = new Date().getTime();
		lastMessageCheckDuration = lastMessageCheckDuration *1.5;
		userIsDead = true;
		lastTimeout = setTimeout(checkForChanges,lastMessageCheckDuration);
	}
	var userIsAlive = function (){
		if (userIsDead) {
			userIsDead = 0; 
			if (lastTimeout)
				clearTimeout(lastTimeout);
			var timeSinceLast = new Date().getTime() - lastMessageCheckTime;
			lastMessageCheckDuration = 5000;
			setTimeout(checkForChanges,timeSinceLast > 5000 ? 0 : 5000 - timeSinceLast);
		}
	}
	var scriptStripper = new RegExp('<script[^>]*>([\u0001-\uFFFF]*?)</script>','img');
	//events.addListener(document.body,"mousemove",userIsAlive);
	//events.addListener(document.body,"keydown",userIsAlive);
	//setTimeout(checkForChanges,1000);
	//clientDataTable = {};
	_p(

/*	pjs.dataTable['js/widget'] = {						*/pjs.dataTable,"js/widget",{
/*		_id:'js/widget',						*/_id:"js/widget",
/*		"defaultStyleClass":"component",						*/"defaultStyleClass":"component",
/*		layout:"",						*/layout:"",
/*		name:"Widget", 						*/name:"Widget",
/*		access:{accessLevel:2}, // TODO: need to make something that won't appear editable						*/access:{accessLevel:2},
/*		render:function(context) {						*/render:function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:
/*		 context.#component = this;						*/context.component=this;_cp=2;case 2:if((_f.v2=
/*		 illum.applyStyles(context.#element,illum.trackedGet(this,"styles"));						*/illum.trackedGet(this,"styles"))===_S){break _s;}_cp=3;case 3:if((_f.v3=illum.applyStyles(context.element,_f.v2))===_S){break _s;}_cp=4;case 4:if((_f.v4=
/*		 var source = illum.trackedGet(this,"layout"); 						*/illum.trackedGet(this,"layout"))===_S){break _s;}var source=_f.v4;
/*		 if (!util.#renderingOnServer)						*/_cp=(!util.renderingOnServer)?5:6;break;case 5:_cp=7;case 7:if((_f.v7=
/*		  this.renderEffect->(context);						*/this.renderEffect(context))===_S){break _s;}_cp=6;break;case 6:_cp=8;case 8:if((_f.v8=
/*		 context.renderLayout->(this,source); 						*/context.renderLayout(this,source))===_S){break _s;}return;case 0:source=_f[0];context=_f[1];_cp=_f.cp;}}return _f.sus(source,context,_cp,this)}
/*		},						*/,
/*		renderEffect:function(){},// no effect by default						*/renderEffect:function(){},
/*		_structure:pjs.dataTable['js/widget_structure'] = {						*/_structure:_p(pjs.dataTable,"js/widget_structure",{
/*			_id:'js/widget_structure',						*/_id:"js/widget_structure",
/*			tagLogic:{type:'object'},						*/tagLogic:{type:"object"},
/*			styles:{type:'string'},						*/styles:{type:"string"},
/*			layout:{type:'string'},						*/layout:{type:"string"},
/*			name:{type:'string'},						*/name:{type:"string"},
/*			render:{type:'function'}						*/render:{type:"function"}})
/*		},  						*/,
/*		styles:"",						*/styles:"",
/*		tagLogic:{_id:'js/widget?1',						*/tagLogic:{_id:"js/widget?1",
/*			action:function(context) {						*/action:function(context){var _this,element,_cp=1;var _f=_frm(arguments);return _f.clsr(function(){_s:while(1){switch(_cp){case 1:
/*				var _this = this;						*/_this=this;_cp=2;case 2:if((_f.v2=_g(
/*				var element = context.element; 						*/context,"element"))===_S){break _s;}element=_f.v2;
/*				if (element.#tagName=="A")						*/if(element.tagName=="A")
/*					element.#href="#";						*/{element.href="#";}_cp=3;case 3:if((_f.v3=
/*				events.addListener->(element,"click",function(evt) {						*/events.addListener(element,"click",function(evt){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*					evt.preventDefault(); // do it first in case there is an error						*/evt.preventDefault())===_S){break _s;}_cp=3;case 3:if((_f.v3=
/*					_this[element.getAttribute->("name")].call->(_this,context); 						*/element.getAttribute("name"))===_S){break _s;}_cp=4;case 4:if((_f.v4=_g(_this,_f.v3))===_S){break _s;}_cp=5;case 5:if((_f.v5=_f.v4.call(_this,context))===_S){break _s;}return;case 0:evt=_f[0];_cp=_f.cp;}}return _f.sus(evt,_cp,this)}))===_S){break _s;}_cp=4;case 4:if((_f.v4=
/*					});						*/
/*				context.renderLayout->(this);						*/context.renderLayout(this))===_S){break _s;}return;}}return _f.sus(this)}).call(this)}
/*			},						*/,
/*			attach:function(context) {						*/attach:function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*				context[context.#element.getAttribute->("name")]=context.#element;						*/context.element.getAttribute("name"))===_S){break _s;}_p(context,_f.v2,context.element);_cp=3;case 3:if((_f.v3=
/*				context.renderLayout->(this);						*/context.renderLayout(this))===_S){break _s;}return;case 0:context=_f[0];_cp=_f.cp;}}return _f.sus(context,_cp,this)}
/*			},						*/,
/*			attachElement:function(context) {						*/attachElement:function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*				context.#component[context.#element.getAttribute->("field")]=context.#element;						*/context.element.getAttribute("field"))===_S){break _s;}_p(context.component,_f.v2,context.element);_cp=3;case 3:if((_f.v3=
/*				context.renderLayout->(this);						*/context.renderLayout(this))===_S){break _s;}return;case 0:context=_f[0];_cp=_f.cp;}}return _f.sus(context,_cp,this)}
/*			},						*/,
/*			dataBound:function(context) {						*/dataBound:function(context){var content,_cp=1;var _f=_frm(arguments);return _f.clsr(function(){_s:while(1){switch(_cp){case 1:
/*				var content = context.#content;						*/content=context.content;
/*				context.#element.#value=content;						*/context.element.value=content;
/*				if (content.#parent) {						*/if(content.parent){
/*					context.#element.#onchange=function() {						*/context.element.onchange=function(){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*						content.#parent.set(content.#field,context.#element.#value);						*/content.parent.set(content.field,context.element.value))===_S){break _s;}return;case 0:_cp=_f.cp;}}return _f.sus(_cp,this)};}_cp=2;case 2:if((_f.v2=
/*					}						*/
/*				}						*/
/*				context.renderLayout->(this);						*/context.renderLayout(this))===_S){break _s;}return;}}return _f.sus(this)}).call(this)}
/*			},						*/,
/*			dialogLink:function(context) {						*/dialogLink:function(context){var self,event,_cp=1;var _f=_frm(arguments);return _f.clsr(function(){_s:while(1){switch(_cp){case 1:
/*				 var self = this;						*/self=this;_cp=2;case 2:if((_f.v2=_g(
/*				 var event = context.element.getAttribute("event");						*/context,"element"))===_S){break _s;}_cp=3;case 3:if((_f.v3=_f.v2.getAttribute("event"))===_S){break _s;}event=_f.v3;_f.c3=
/*				 if (!event || event.length == 0)						*/!event;_cp=(!_f.c3)?4:5;break;case 4:_cp=6;case 6:if((_f.v6=_g(event,"length"))===_S){break _s;}_f.c3=_f.v6==0;_cp=5;break;case 5:if(_f.c3)
/*					  event = "click";						*/{event="click";}_cp=7;case 7:if((_f.v7=_g(
/*				 events.addListener(context.element,event,function(evt) {						*/context,"element"))===_S){break _s;}_cp=8;case 8:if((_f.v8=events.addListener(_f.v7,event,function(evt){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*					  evt.preventDefault(); // we don't want to navigate to this url						*/evt.preventDefault())===_S){break _s;}_cp=3;case 3:if((_f.v3=
/*					  var target = illum.evaluateField(context);   						*/illum.evaluateField(context))===_S){break _s;}var target=_f.v3;_cp=4;case 4:if((_f.v4=_g(
/*					  var dialogContext = illum.createDialog(context,context.element.getAttribute->("name"),target);						*/context,"element"))===_S){break _s;}_cp=5;case 5:if((_f.v5=_f.v4.getAttribute("name"))===_S){break _s;}_cp=6;case 6:if((_f.v6=illum.createDialog(context,_f.v5,target))===_S){break _s;}var dialogContext=_f.v6;return;case 0:dialogContext=_f[0];target=_f[1];evt=_f[2];_cp=_f.cp;}}return _f.sus(dialogContext,target,evt,_cp,this)}))===_S){break _s;}_cp=9;case 9:if((_f.v9=
/*				 });						*/
/*				 context.renderLayout->(this);						*/context.renderLayout(this))===_S){break _s;}return;}}return _f.sus(this)}).call(this)}
/*			},						*/,
/*			display:function(context) {						*/display:function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*				var value = illum.evaluateField(context);						*/illum.evaluateField(context))===_S){break _s;}var value=_f.v2;_cp=3;case 3:if((_f.v3=
/*				context.renderLayout->(this,value);						*/context.renderLayout(this,value))===_S){break _s;}return;case 0:value=_f[0];context=_f[1];_cp=_f.cp;}}return _f.sus(value,context,_cp,this)}
/*			},						*/,
/*			each:function(context) {						*/each:function(context){var source,content,maxHeight,parent,element,hasForParent,self,pageSize,_cp=1;var _f=_frm(arguments);return _f.clsr(function(){_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*			 var content = illum.evaluateField(context);						*/illum.evaluateField(context))===_S){break _s;}content=_f.v2;
/*			 var element = context.#element;						*/element=context.element;_cp=3;case 3:if((_f.v3=
/*			 var pageSize = element.getAttribute("pageSize");						*/element.getAttribute("pageSize"))===_S){break _s;}pageSize=_f.v3;_cp=4;case 4:if((_f.v4=
/*			 var hasForParent = element.#parentNode.getAttribute("logic") == "for";						*/element.parentNode.getAttribute("logic"))===_S){break _s;}hasForParent=_f.v4=="for";
/*			 var parent = hasForParent ? element.#parentNode : element;						*/parent=hasForParent?element.parentNode:element;
/*			 var source = element.#innerHTML;						*/source=element.innerHTML;
/*			 if (!hasForParent)						*/if(!hasForParent)
/*			  element.#innerHTML = "";						*/{element.innerHTML="";}
/*			 var self = this;						*/self=this;
/*			 if (content instanceof Array)						*/_cp=(content instanceof Array)?5:6;break;case 5:_cp=7;case 7:if((_f.v7=
/*			  Array.forEach(content,function(val,i) {						*/Array.forEach(content,function(val,i){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_f.c1;
/*			   var itemEl = hasForParent ? element.cloneNode(true) : element.ownerDocument.createElement("span");						*/_cp=(hasForParent)?2:3;break;case 2:_cp=5;case 5:if((_f.v5=element.cloneNode(true))===_S){break _s;}_f.c1=_f.v5;_cp=4;break;case 3:_cp=6;case 6:if((_f.v6=_g(element,"ownerDocument"))===_S){break _s;}_cp=7;case 7:if((_f.v7=_f.v6.createElement("span"))===_S){break _s;}_f.c1=_f.v7;_cp=4;break;case 4:var itemEl=_f.c1;
/*			   if (!hasForParent)						*/if(!hasForParent)
/*			    itemEl.className = "listItem";						*/{_p(itemEl,"className","listItem");}_cp=8;case 8:if((_f.v8=
/*			   var childContext = context.createChild->(parent.appendChild(itemEl));						*/parent.appendChild(itemEl))===_S){break _s;}_cp=9;case 9:if((_f.v9=context.createChild(_f.v8))===_S){break _s;}var childContext=_f.v9;
/*			   childContext.#content = val;						*/childContext.content=val;_cp=10;case 10:if((_f.v10=
/*			   childContext.renderLayout->(self,hasForParent?null:source);						*/childContext.renderLayout(self,hasForParent?null:source))===_S){break _s;}return;case 0:itemEl=_f[0];childContext=_f[1];val=_f[2];i=_f[3];_cp=_f.cp;}}return _f.sus(itemEl,childContext,val,i,_cp,this)}))===_S){break _s;}_cp=6;break;case 6:
/*			  });						*/
/*			  itemEl = element;						*/itemEl=element;
/*			  if (hasForParent)						*/_cp=(hasForParent)?8:9;break;case 8:_cp=10;case 10:if((_f.v10=
/*			   parent.removeChild(element);						*/parent.removeChild(element))===_S){break _s;}_cp=9;break;case 9:_cp=11;case 11:if((_f.v11=
/*			  var maxHeight = parent.getAttribute("maxHeight");						*/parent.getAttribute("maxHeight"))===_S){break _s;}maxHeight=_f.v11;
/*			  if (!maxHeight)						*/if(!maxHeight)
/*			   return; 						*/{return;}
/*			  if (parent.#offsetHeight > maxHeight)						*/if(parent.offsetHeight>maxHeight)
/*			    parent.#style.#height=maxHeight + "px";						*/{parent.style.height=maxHeight+"px";}return;}}return _f.sus(this)}).call(this)}
/*			},						*/,
/*			field:function(context) {						*/field:function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*			      var value = illum.evaluateField(context);						*/illum.evaluateField(context))===_S){break _s;}var value=_f.v2;_cp=3;case 3:if((_f.v3=
/*			      var assignTo = context.#element.getAttribute->("assignTo");						*/context.element.getAttribute("assignTo"))===_S){break _s;}var assignTo=_f.v3;_f.c3=
/*			      if (assignTo && assignTo.length > 1)						*/assignTo;_cp=(_f.c3)?4:5;break;case 4:_cp=6;case 6:if((_f.v6=_g(assignTo,"length"))===_S){break _s;}_f.c3=_f.v6>1;_cp=5;break;case 5:if(_f.c3)
/*			       context[assignTo] = value;						*/{_p(context,assignTo,value);}
/*			      else						*/
/*			       context.#content = value;						*/ else context.content=value;_cp=7;case 7:if((_f.v7=
/*			      context.renderLayout->(this);						*/context.renderLayout(this))===_S){break _s;}return;case 0:value=_f[0];assignTo=_f[1];context=_f[2];_cp=_f.cp;}}return _f.sus(value,assignTo,context,_cp,this)}
/*			},						*/,
/*			"for":function(context) {						*/"for":function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*					context.renderLayout(this);						*/context.renderLayout(this))===_S){break _s;}return;case 0:context=_f[0];_cp=_f.cp;}}return _f.sus(context,_cp,this)}
/*			},						*/,
/*			"if":function(context) {						*/"if":function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*			 var value = illum.evaluateField(context);						*/illum.evaluateField(context))===_S){break _s;}var value=_f.v2;
/*			 if (value) {						*/_cp=(value)?3:4;break;case 3:_cp=6;case 6:if((_f.v6=
/*			      var assignTo = context.#element.getAttribute->("assignTo");						*/context.element.getAttribute("assignTo"))===_S){break _s;}var assignTo=_f.v6;
/*			      if (assignTo && assignTo.#length > 1)						*/if(assignTo&&assignTo.length>1)
/*			       context[assignTo] = value;						*/{_p(context,assignTo,value);}
/*			      else						*/
/*			       context.#content = value;						*/ else context.content=value;_cp=7;case 7:if((_f.v7=
/*			      context.renderLayout->(this);						*/context.renderLayout(this))===_S){break _s;}_cp=5;break;case 4:_cp=8;case 8:if((_f.v8=
/*			 }						*/
/*			 else						*/
/*			  context.renderLayout->(this," ");						*/context.renderLayout(this," "))===_S){break _s;}_cp=5;break;case 5:return;case 0:value=_f[0];assignTo=_f[1];context=_f[2];_cp=_f.cp;}}return _f.sus(value,assignTo,context,_cp,this)}
/*			},						*/,
/*			hyperlink:function(context) {						*/hyperlink:function(context){var target,_cp=1;var _f=_frm(arguments);return _f.clsr(function(){_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*			 var target = illum.evaluateField(context);						*/illum.evaluateField(context))===_S){break _s;}target=_f.v2;
/*			 if (context.#element.#tagName=="A")						*/_cp=(context.element.tagName=="A")?3:4;break;case 3:_cp=5;case 5:if((_f.v5=_g(
/*			  context.#element.#href="#" + encodeURI->(target.name);						*/target,"name"))===_S){break _s;}_cp=6;case 6:if((_f.v6=encodeURI(_f.v5))===_S){break _s;}context.element.href="#"+_f.v6;_cp=4;break;case 4:_cp=7;case 7:if((_f.v7=
/*			 events.addListener(context.#element,"click",function(evt) {						*/events.addListener(context.element,"click",function(evt){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*			  evt.preventDefault();						*/evt.preventDefault())===_S){break _s;}_cp=3;case 3:if((_f.v3=
/*			  context.navigate->(target);						*/context.navigate(target))===_S){break _s;}return;case 0:evt=_f[0];_cp=_f.cp;}}return _f.sus(evt,_cp,this)}))===_S){break _s;}_cp=8;case 8:if((_f.v8=
/*			 });						*/
/*			 context.renderLayout->(this);						*/context.renderLayout(this))===_S){break _s;}return;}}return _f.sus(this)}).call(this)}
/*			},						*/,
/*			property:function (context) {						*/property:function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*			 var value = illum.evaluateField(context);						*/illum.evaluateField(context))===_S){break _s;}var value=_f.v2;_cp=3;case 3:if((_f.v3=
/*			 var property = context.#element.getAttribute("property") || "value";						*/context.element.getAttribute("property"))===_S){break _s;}var property=_f.v3||"value";_cp=4;case 4:if((_f.v4=_g(
/*			 context.element[property] = value;						*/context,"element"))===_S){break _s;}_p(_f.v4,property,value);_cp=5;case 5:if((_f.v5=
/*			 context.renderLayout(this,value,5);						*/context.renderLayout(this,value,5))===_S){break _s;}return;case 0:value=_f[0];property=_f[1];context=_f[2];_cp=_f.cp;}}return _f.sus(value,property,context,_cp,this)}
/*			},						*/,
/*			text:function(context) {						*/text:function(context){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:_cp=2;case 2:if((_f.v2=
/*			 var value = illum.evaluateField(context);						*/illum.evaluateField(context))===_S){break _s;}var value=_f.v2;
/*			 var element = context.#element;						*/var element=context.element;_cp=7;case 7:if((_f.v7=
/*			 switch(element.getAttribute("richtext")) {						*/element.getAttribute("richtext"))===_S){break _s;}_cp=8;case 8:if((_f.v8=element.getAttribute("richtext"))===_S){break _s;}_cp=_f.v7=="true"?6:_f.v8=="allowHandlers"?5:4;break;case 6:_cp=9;case 9:if((_f.v9=
/*			  case "true" : 						*/
/*			  	var stripped = value.replace(scriptStripper,'');						*/value.replace(scriptStripper,""))===_S){break _s;}var stripped=_f.v9;
/*			  	if (typeof value == "object") {						*/_cp=(typeof value=="object")?10:11;break;case 10:_cp=12;case 12:if((_f.v12=_f._new(
/*			  		stripped = new String(stripped);						*/String,[stripped]))===_S){break _s;}stripped=_f.v12;
/*			  		stripped.#field = value.#field;						*/stripped.field=value.field;
/*			  		stripped.#parent = value.#parent;						*/stripped.parent=value.parent;_cp=11;break;case 11:
/*			  	}						*/
/*			  	value = stripped; // fall through						*/value=stripped;case 5:_cp=13;case 13:if((_f.v13=
/*			  case "allowHandlers" : context.renderLayout->(this,value,3); break;						*/context.renderLayout(this,value,3))===_S){break _s;}_cp=3;break;case 4:_cp=14;case 14:if((_f.v14=
/*			  default :						*/
/*			   context.renderLayout->(this,value,4);						*/context.renderLayout(this,value,4))===_S){break _s;}case 3:return;case 0:value=_f[0];element=_f[1];stripped=_f[2];context=_f[3];_cp=_f.cp;}}return _f.sus(value,element,stripped,context,_cp,this)}}});_p(
/*			 } 						*/
/*			}						*/
/*		}						*/
/*	}						*/
/*	pjs.dataTable['js/widget']._structure.prototype = pjs.dataTable['js/widget'];						*/pjs.dataTable["js/widget"]._structure,"prototype",pjs.dataTable["js/widget"]);
/*							*/

	if (!document.body) {
		alert("Illuminate was initialized before the document body was available. Make sure that the illuminate.js is not declared before the opening body tag");
	}
	arVersion=navigator.appVersion.split("MSIE");
	version=parseFloat(arVersion[1]);
	illum.pngFix=((version>=5.5&&version<7)&&(document.body.filters));



/* This section handles core rendering*/

// TODO: Rather than doing this, lets go through the context children that are removed and do this on a timed schedule
// We are getting rid of component and content, but what about any other custom properties that were set?
// We can compare it to comparitiveElement to see if it should be deleted but that could be costly
function setInnerHTMLWithCleanup(element,src) {
//	debug("start setInnerHTMLWithCleanup ");
/*	if (isIE) {
		var children = element.getElementsByTagName("*");
		for (var i=0;i<children.length;i++) {
			children[i].context = null;
			children[i].onclick = null;
/*			if (children[i].context) {
	//			if (children[i].context.component)
		//			children[i].context.component._destroy();
				if (children[i].context.element)
					children[i].context.element = null;
				children[i].context = null;
	//			if (children[i].styleId)
		//			document.getElementsByTagName("head")[0].removeChild(byId(children[i].styleId));
			}
		}
	}*/
//	debug("done setInnerHTMLWithCleanup ");
	if (element.innerHTML != src)
		element.innerHTML = src;
}

illum.nextContextId = 1;
illum.rootContext = {
	Construct : function() {},
	lookupTable : {},
	element : document.body,	
	_structure : Context,
	id : 0,
	children : [], // this could be created dynamically
	createChild : function(element) {
		this.Construct.prototype = this;
		var child = new this.Construct();
		child.parent = this;
		child.id = illum.nextContextId++; // TODO: Is this used?
		child.lookupTable = {};
		child.children =[]; // TODO: This and the one above should be done as needed, to minimize object creation.
		if (element) {
			child.element = element;
			element.context = child;
		}
		this.children[this.children.length] = child;
		return child;
	},
	clearChildren : function() {
		if (illum.isIE) {
			for (var i = 0; i < this.children.length; i++) {
				var child = this.children[i];
				var element = child.element;
				if (element.sourceElement) {
					element.sourceElement.sourceString=0;
					element.sourceElement=0;
				}
				//element.onclick=element.ondrop=element.onpaste=element.onbeforepaste=element.ondragstart=element.oncut=element.onmouseover=element.onmouseout=element.onkeydown=null;
				element.context=null;
/*				purge(element.sourcePlacementElement);
				purge(element.sourceElement);
				purge(child.sourceElement);
				purge(element);*/
//				delete child.element;
				delete child.sourceElement;
				child.clearChildren();
			}
		}
		this.children = [];
	},
	render : function() {
		var context = this;
		while (!context.hasOwnProperty("component"))
			context = context.parent;
		context.component.render(context);
	},
	remove : function() {
		if (this.element)
			this.element.parentNode.removeChild(this.element);
		this.clearChildren();
		this.element = null;
		var parentChildren = this.parent.children;
		var index = Array.indexOf(parentChildren,this);
		if (index > -1)
			parentChildren.splice(index,1);
	},
	isOrphaned : function() {
		if (!this.parent)
			return false;
		if (Array.indexOf(this.parent.children,this) == -1)
			return true;
		return this.parent.isOrphaned();
	},
		/* This all should be moved to the body component */
		navigate : function(target) {
				//debug("navigating to " + target);
				var njf = _frm(arguments);
				if (!njf.scp)
					target = njf[0];
				illum.pageInUrl = typeof(target) =="string";
				if (illum.pageInUrl)
				{
/*					if (target.indexOf("/")!=-1) {
						var subTarget = target.substring(target.indexOf("/")+1);
						target = target.substring(0,target.indexOf("/"));
					}
					*/
/*					var self = this;
					if (!this.navigationContainer.navigationList) { //This means the navigationList is not available yet, we will wait until it is
						//TODO: We should actually use a different technique if the navigationList is not available yet
						setTimeout(function() { self.navigate(target) },200);
						return;
					}*/					

					var target =this.navigationContainer.getPageByName(target);
					if (!target)
						return;
					if (target==_S) {
						return njf.sus();
					}
				}
				this.navigationContainer._currentValue = target;
				for (var i=0;i<this.navigationContainer._navigationListeners.length;i++) {
					var listener = this.navigationContainer._navigationListeners[i]
//						alert("firing navigate " + listener + " out of " + this.navigationContainer._navigationListeners.length);
					if (listener.isSubListener) {
						if (subTarget)
							listener.navigate(subTarget);
					}
					else
						listener.navigate(target);
				}
			},
		navigationContainer : {
			_navigationListeners : new Array(),
			addNavigationListener : function(listener) {
				if (Array.indexOf(this._navigationListeners,listener) == -1) {
					this._navigationListeners.push(listener);
				}
			},
			setLocationString : function(location) {
				if (!illum.pageInUrl)
					urlHistory.addLocationToHistory(location);
			},
			getCurrentTarget : function(){
				if (this._currentValue) 
					return this._currentValue;
				var newCurrentValue; 
				if (illum.targetPageName != "null") {
					return this.getPageByName(illum.targetPageName);
				}
				if ((newCurrentValue=pjs.get(this.navigationList,0))==strands.Suspension) return strands.Suspension;
				return this._currentValue=newCurrentValue;				
			},
			getPageByName : function(target) {
					if (target.substring(0,3) == "id:")
						return pjs.load(target.substring(3));					
					var correctPages = this.navigationList;
					if (!correctPages) {
						illum.targetPageName = target;
						return;
					}
					if (target)
						correctPages = pjs.query('','select * from ? where name=?',correctPages,target);
					if (correctPages == _S || pjs.get(correctPages,"length")==_S) return _S;
					if (pjs.get(correctPages,"length") > 0) {
						if ((target = pjs.get(correctPages,0))==_S) return _S;
					}
					else {
						alert("The requested page " + target + " is not available.");
						return;
					}
					return target;
			}
		},
		//navigationList : this should be set to the current content;
		/* This all should be moved to the body component */
	// renderLayout renders the html for a context.  The first parameter is optional only if no required to proces
	RENDER_MODE: {ALL : 0,
	RICH_TEXT : 1,
	RICH_TEXT_NO_JS_HANDLERS : 3,
	TEXT_ONLY : 4,
	NO_SOURCE: 5},
	renderLayout : function (component,source,renderMode) {
		//debug("rendering " + component + " " + source);
		var targetElement = this.element;
		if (targetElement === null)
			throw DontRepeat;
		if (source && renderMode != 5) {
			if (source.parent) // it has tracking on the source
				illum.addContextListener(this,this.sourceParent = source.parent);
			
			if (source.innerHTML)
				source = source.innerHTML;
			if (renderMode == 4) {
				setInnerHTMLWithCleanup(targetElement,"");
				targetElement.appendChild(document.createTextNode(source));
			}
			else {
				if (source.render) {
					source.render(this);
					return;
				}
				setInnerHTMLWithCleanup(targetElement,source);
			}
			this.clearChildren();
		}
		this._renderInside(component,targetElement);
	},
	_renderInside : function(component,source) {
		var children = [];
		// we need a create a copy of the childNodes because it can morph as we iterate
		for (var i = 0; i < source.childNodes.length;i++) {
			children[i]=source.childNodes[i];
		}
		
		
/*	var tagHandler = function (tagName,tagCtxt) {
			var handler = component.tagLogic[tagName]; 
			if (handler)
				handler.call(component,tagCtxt); // we need to resume so we can abandon orphaned cases
			else
				setInnerHTMLWithCleanup->(source,"There was no tag handler for \"" + name + "\"");
			}*/
			var tagHandler=function(tagName,tagCtxt){var _f = _frm(arguments);var _cp=_f.scp;_s:while(1){switch(_cp){case 1:
var handler=component.tagLogic[tagName];
_cp=(handler)?2:3;break;case 2:_cp=5;case 5:if((_f.v5=
handler.call(component,tagCtxt))===_S){break _s;}_cp=4;break;case 3:

setInnerHTMLWithCleanup(source,"There was no tag handler for \""+name+"\"");_cp=4;break;case 4:return;case 0:
			if (!tagCtxt) {
				if (_f[2].isOrphaned())
				{
					//debug("abondoning an orphaned child from tagHandler " + name);
					strands.clearSuspension();
					return;
				}
			}
handler=_f[0];tagName=_f[1];tagCtxt=_f[2];_cp=_f.cp;}}return _f.sus(handler,tagName,tagCtxt,_cp,this)};

 		for (var i = 0; i < children.length;i++) {
			source = children[i];
			if (source.nodeType == 1) {
				var name = source.getAttribute("logic");
				if (name != null && name.length > 0) {
					// execute the tag method for the given element
					tagHandler(name,this.createChild(source));
				}
				else {
					if (source.tagName.toUpperCase() == "IMG") {
						var imgName;
						if (imgName = source.getAttribute("originalsrc")) {
							var extension = imgName.toUpperCase().substring(imgName.lastIndexOf(".") +1);
							if ((source.style.width || source.style.height) && (extension == "JPG" || extension == "JPEG")) // TODO: This should be currentStyle
								source.src = imgName+ "-"
									+ util.convertDimToNum(source.style.width) + "x" + util.convertDimToNum(source.style.height) + ".resized";
							else
								source.src = imgName;
						}
						else 
							var extension = source.src.toUpperCase().substring(source.src.lastIndexOf(".") +1);
						if (illum.pngFix) {
					      if (extension == "PNG" && source.fixPng != "false")
						     illum.fixPng(source);
						}
						if (illum.isIE && !(illum.pngFix && extension== "PNG")){
							events.addListener(source,"load",function(evt) { 
								var img = evt.target;// This is to fix the bizarre image not loading bug in IE
								img.width = img.width+1;
								img.width = img.width-1;
							});
						}
					}
					this._renderInside(component,source);
				}
			}
			else  {// handles  text nodes
//						targetElement.appendChild(source.cloneNode(false));
			}
		}
	}


}



urlHistory = {
	addLocationToHistory : function(location) {
		setTimeout(function() {
			location = encodeURIComponent(location);
			urlHistory.lastLocation = location;
			if (!util.renderingOnServer) {
				window.location.hash = location;
				if (illum.isIE) {
					urlHistory.navFrame().src='res/iframeHistory.html?' + location;
				}
			}
		},100);
	},
	onURLChange : function(href) {
			urlHistory.lastLocation = href;
			illum.rootContext.navigate(decodeURIComponent(href));
	},
	navFrame : function() {
		var navFrame = illum.byIdOrCreate('navFrame','iframe');
		navFrame.style.display='none';
		return navFrame;
	},
	onIframeChange : function(href) { // IE Only
		if (!util.renderingOnServer)
			location.hash = href;
		if (urlHistory.lastLocation != href) 
			urlHistory.onURLChange(href);
	},
	getHash : function() {
		var href = location.href;
		var hashIndex = href.indexOf("#");
		if (hashIndex > 0) 
			return href.substring(hashIndex + 1);
		else
			return "";
	},
	checkURL : function() {
		if (!util.renderingOnServer) {
			setTimeout(urlHistory.checkURL,200); // TODO: reenable this
			util. cleanup();

			var hash = urlHistory.getHash();
			if (urlHistory.lastLocation === undefined) {
				if (illum.isIE)
					urlHistory.navFrame().src='res/iframeHistory.html?';
				urlHistory.lastLocation = "";
			}
			if (hash != urlHistory.lastLocation && hash.substring(0,7) != "anchor_") {
				if (hash.indexOf("/edit") >-1) // if a user adds a /edit to the end of the hash, we should go to edit mode
					return illum.editThisPage(hash.substring(0,hash.length-5));
				if (illum.isIE)
					urlHistory.navFrame().src='auth/iframeHistory.html?' + hash; // this will trigger the onURLChange
				urlHistory.onURLChange(hash);
			}
		}
	}
}
pjs.status = function(status) {
	if (document.body) { // the first time it is called before the body is present, may want to fix this
		var element = illum.byIdOrCreate('status','div');
		element.style.cssText="position:absolute;top:0px;left:0px;z-index:10;background:url('res/spinner.gif') white no-repeat;border:1px solid black;padding:5px;padding-left:25px;font-family:arial"
		if (status) {
			document.body.style.cursor="progress";
			element.innerHTML= status;
			element.style.display = "block";
		}
		else {
			document.body.style.cursor="auto";
			element.innerHTML="";
			element.style.display = "none";			
		}		
	}
}
byId = function (id) {
	return document.getElementById(id);
}

debug = function (str) {
	if (debugMode) { // TODO: reenable this
		if (!util.renderingOnServer) {
			if (window.console)
				return console.log(str);
			var div = document.createElement("DIV");			
			var newDate = new Date();
			var test = {};
		    var text = document.createTextNode(" " + str);
		    div.appendChild(text);
			var debugDiv = illum.byIdOrCreate("debugger",'div');
			if (debugDiv.childNodes[0])
				debugDiv.insertBefore(div,debugDiv.childNodes[0]);
			else
				debugDiv.appendChild(div);
		}
		else
			alert(str);
	}
}
//TODO: Need to get rid of this
util.serverAction=function(){with(_frm(this,arguments,["className","method","parameters"],["reqString","id"])){nj:while(1){switch(_cp){case 0:
var basis;
parameters['class']=className;
parameters.method = method;
/*for (i in parameters) {
	var value = parameters[i];
	while(value && !value.hasOwnProperty("id") && (basis = value.alterationProto || value.__proto__)) 
		value = basis;
	parameters[i] = value; //JSON.stringify(exportable(value,1));	
}*/

_cp=1;case 1:if((_r.v1=
persevere.request("call",parameters,"processing"))==_S){return _s();}
if (_r.v1 instanceof Error) throw _r.v1;
return _r.v1;return;case -1:return _s();}}}};

if (window.HTMLElement && HTMLElement.prototype.__defineGetter__)
	HTMLElement.prototype.__defineGetter__("currentStyle", function() {    return getComputedStyle(this, null);});
	
/*function purge(d) {    if (!d) return;   	
if (d.$_handlers) d.$_handlers = null;
if (d.sourceString) d.sourceString=null; 
var a = d.attributes, i, l, n;  
  if (a) {        l = a.length;        for (i = 0; i < l; i += 1) {            
  	n = a[i].name;    
  	if (typeof d[n] == "function")
  	d[n] = null;            }    }    
  	
  	a = d.childNodes;    if (a) {        l = a.length;        for (i = 0; i < l; i += 1) {            purge(d.childNodes[i]);        }    }}
*/
})()
